﻿using System;
using System.Linq;
using NUnit.Framework;
using NaturalKeySpike.Common.DataAccess;

namespace NaturalKeySpike {
    [TestFixture]
    public class When_sharing_part_of_primary_key {
        private INhibernateUnitOfWork _uow;
        private IRepository _repository;
        private int _tableAId;

        [SetUp]
        public void Before_each_test() {
            _tableAId = IdGenerator.NextId();
            CommitAndResetUow();
        }

        [TearDown]
        public void After_each_test() {
            _uow.Dispose();
        }

        [TestFixtureTearDown]
        public void After_all_tests() {
            CommitAndResetUow();
            foreach (var tableA in _repository.Find<TableA>()) {
                _repository.Remove(tableA);
            }
            _uow.Commit();
        }

        [Test]
        public void Can_insert_table_a() {
            _repository.Add(new TableA(_tableAId));
            CommitAndResetUow();

            var tableA = _repository.Get<TableA>(_tableAId);
            Assert.IsNotNull(tableA);
            Assert.AreEqual(_tableAId, tableA.TableAId);
            Assert.AreEqual("A" + _tableAId, tableA.Name);
            Assert.False(tableA.TableBs.Any());
            Assert.False(tableA.TableCs.Any());
        }

        [Test]
        public void Can_insert_table_b() {
            var tableA = _repository.Add(new TableA(_tableAId));
            tableA.AddB(IdGenerator.NextId());
            CommitAndResetUow();

            tableA = _repository.Get<TableA>(_tableAId);
            Assert.AreEqual(1, tableA.TableBs.Count);
            Assert.False(tableA.TableCs.Any());
        }

        [Test]
        public void Can_insert_table_c() {
            var tableA = _repository.Add(new TableA(_tableAId));
            tableA.AddC(IdGenerator.NextId());
            CommitAndResetUow();

            tableA = _repository.Get<TableA>(_tableAId);
            Assert.False(tableA.TableBs.Any());
            Assert.AreEqual(1, tableA.TableCs.Count);
        }

        [Test]
        public void Can_insert_table_d() {
            var tableA = _repository.Add(new TableA(_tableAId));
            var tableB = tableA.AddB(IdGenerator.NextId());
            var tableC = tableA.AddC(IdGenerator.NextId());

            tableB.AddD(IdGenerator.NextId(), tableC);

            CommitAndResetUow();

            tableA = _repository.Get<TableA>(_tableAId);
            Assert.False(tableA.TableBs.Any());
            Assert.AreEqual(1, tableA.TableBs.Count);
            Assert.AreEqual(1, tableA.TableCs.Count);
            Assert.AreEqual(1, tableA.TableBs[0].TableDs.Count);
            Assert.AreEqual(1, tableA.TableCs[0].TableDs.Count);
            Assert.AreEqual(tableA.TableBs[0].TableDs[0], tableA.TableCs[0].TableDs[0]);
        }

        private void CommitAndResetUow() {
            if (_uow != null) {
                _uow.Commit();
                _uow.Dispose();
            }

            _uow = new NhibernateUnitOfWork();
            _repository = new NhibernateRepository(_uow);
        }
    }
}
